home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / simplerd.lha / simplerad / FinalFTP / Light / raycyl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-21  |  3.5 KB  |  109 lines

  1. /**********************************************************************/
  2. /* raycyl.c                                                           */
  3. /*                                                                    */
  4. /* Ray / cylinder intersection routines                               */
  5. /* Modified from Optik v(1.2e) (C) 1987 John Amanatides & Andrew Woo  */
  6. /*                                                                    */
  7. /* Copyright (C) 1992, Bernard Kwok                                   */
  8. /* All rights reserved.                                               */
  9. /* Revision 1.0                                                       */
  10. /* May, 1992                                                          */
  11. /**********************************************************************/
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include "geo.h"
  15. #include "misc.h"
  16. #include "struct.h"
  17. #include "ray.h"
  18. #include "io.h"
  19.  
  20. /**********************************************************************/
  21. extern OptionType Option;
  22. extern RayStats_Type RayStats;
  23.  
  24. /**********************************************************************/
  25. /* Intersect a ray with a unit cylinder. Return any hit */
  26. /**********************************************************************/
  27. void RayCylinder(ray, hit, optr)
  28.      register Ray *ray;
  29.      register HitData *hit;
  30.      register Objectt *optr;
  31. {
  32.   double a,b,c,r1,r2,t,discrim,x,y,z;
  33.  
  34.   RayStats.rayCylinder++;  
  35.   if (Option.debug)
  36.     printf("\t\tRay-Cylinder: (%g,%g,%g) > (%g,%g,%g)\n",
  37.        ray->origin.x, ray->origin.y, ray->origin.z, 
  38.        ray->dir.x, ray->dir.y, ray->dir.z);
  39.   
  40.   /* find a,b,c of at**2 +bt +c */
  41.   a= ray->dir.x*ray->dir.x + ray->dir.y*ray->dir.y;
  42.   b= 2.0 * (ray->origin.x * ray->dir.x + ray->origin.y * ray->dir.y);
  43.   c= ray->origin.x * ray->origin.x + ray->origin.y * ray->origin.y - 1.0;
  44.  
  45.   /* Calculate discriminant */
  46.   discrim= b*b - 4.*a*c;
  47.   if (discrim > 0.0) {
  48.     /* find closest intersection (also watch for stability)  */
  49.     if (b < 0.0) {
  50.       r2= (-b + sqrt(discrim)) / (2.0 * a);
  51.       r1= c / (a * r2);
  52.     } else {
  53.       r1= (-b - sqrt(discrim)) / (2.0 * a);
  54.       r2= c / (a * r1);
  55.     }
  56.     if (r1 <= MIN_DISTANCE)    /* for round-off errors */
  57.       t= r2;
  58.     else t= r1;
  59.  
  60.     /* Store intersection info */
  61.     if ((t > MIN_DISTANCE) && (t < hit->distance)) {
  62.       z = ray->origin.z + t * ray->dir.z;
  63.       if (z > -1.0 && z < 1.0) {
  64.     x = ray->origin.x + t * ray->dir.x;
  65.     y = ray->origin.y + t * ray->dir.y;
  66.     RayStats.intCylinder++;  
  67.     Store_HitInter(hit, optr, t, x, y, z);
  68.     if (!ray->shadow) {
  69.       Store_HitNorm(hit, x, y, 0.0);
  70.       hit->texture= hit->intersect;
  71.     }
  72.       }
  73.     }
  74.   }
  75.  
  76.   /* Check the two disks of the cylinder */
  77.   if (ray->dir.z < -DAMN_SMALL || ray->dir.z > DAMN_SMALL) {
  78.     /* check top disk */
  79.     t= (1.0 - ray->origin.z) / ray->dir.z;
  80.     if (t > MIN_DISTANCE && t < hit->distance) {
  81.       x= ray->origin.x + t*ray->dir.x;
  82.       y= ray->origin.y + t*ray->dir.y;
  83.       /* within circle, store hit */
  84.       if (x*x + y*y < 1.0) {
  85.     RayStats.intCylinder++;  
  86.     Store_HitInter(hit, optr, t, x, y, 1.0);
  87.     if (!ray->shadow) {
  88.       Store_HitNorm(hit, 0.0, 0.0, 1.0);
  89.       hit->texture= hit->intersect;
  90.     }
  91.       }
  92.     }
  93.  
  94.     /* check bottom disk */
  95.     t= (-1.-ray->origin.z)/ray->dir.z;
  96.     if (t > MIN_DISTANCE && t < hit->distance) {
  97.       x= ray->origin.x + t*ray->dir.x;
  98.       y= ray->origin.y + t*ray->dir.y;
  99.       if (x*x + y*y < 1.) {
  100.     RayStats.intCylinder++;  
  101.     Store_HitInter(hit, optr, t, x, y, -1.);
  102.     if (!ray->shadow) {
  103.       Store_HitNorm(hit, 0., 0., -1.);
  104.     }
  105.       }
  106.     }
  107.   }
  108. }
  109.